﻿#region File and License Information
/*
<File>
	<License>
		Copyright © 2009 - 2017, Daniel Vaughan. All rights reserved.
		This file is part of Calcium (http://calciumsdk.net), 
		which is released under the MIT License.
		See file /Documentation/License.txt for details.
	</License>
	<CreationDate>2010-08-18 17:44:10Z</CreationDate>
</File>
*/
#endregion

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using Microsoft.Phone.Controls;
using Outcoder.Services.MessageService;
using Outcoder.UI.Xaml.Controls;

namespace Outcoder.Services.Implementation
{
	public partial class MessageService
	{
		public override void AskQuestion<TResponse>(
			IQuestion<TResponse> question, 
			Action<QuestionResult<TResponse>> resultHandler)
		{
			ArgumentValidator.AssertNotNull(question, "question");
			ArgumentValidator.AssertNotNull(resultHandler, "resultHandler");

			/* TODO: Add an extensibility point here so that new types of questions can be added using IoC. */

			var textResponseQuestion = question as TextResponseQuestion;
			var handler = resultHandler as Action<QuestionResult<TextResponse>>;

			if (textResponseQuestion == null || handler == null)
			{
				throw new NotImplementedException("Currently this method only supports TextResponse questions.");
			}

			AskQuestionWithTextResponse(textResponseQuestion, handler);
//			if (!typeof(TextResponse).IsAssignableFrom(typeof(TResponse)))
//			{
//				throw new NotImplementedException("Currently this method only supports TextResponse questions.");
//			}
		}

		public override Task<QuestionResult<TResponse>> AskQuestionAsync<TResponse>(
			IQuestion<TResponse> question)
		{
			ArgumentValidator.AssertNotNull(question, "question");

			var twoButtonQuestion = question as TwoButtonQuestion;
			if (twoButtonQuestion == null)
			{
				throw new NotImplementedException("Currently this async method only supports TwoButtonQuestion questions.");
			}

			string caption = twoButtonQuestion.Caption != null ? twoButtonQuestion.Caption.ToString() : null;
			string message = twoButtonQuestion.Body != null ? twoButtonQuestion.Body.ToString() : null;

			CustomMessageBox messageBox = new CustomMessageBox()
				{
					LeftButtonContent = twoButtonQuestion.LeftButtonContent,
					RightButtonContent = twoButtonQuestion.RightButtonContent,
					Caption = caption,
					Message = message
				};

			var source = new TaskCompletionSource<QuestionResult<TResponse>>();

			messageBox.Dismissed += (sender, args) =>
				{
					TwoButtonResponseValue responseValue;
					
					switch (args.Result)
					{
						case CustomMessageBoxResult.LeftButton:
							responseValue = TwoButtonResponseValue.LeftButton;
							break;
						case CustomMessageBoxResult.RightButton:
							responseValue = TwoButtonResponseValue.RightButton;
							break;
						default:
							responseValue = TwoButtonResponseValue.None;
							break;
					}

					//TwoButtonResponse response = new TwoButtonResponse(responseValue);
					var result = new QuestionResult<TResponse>((TResponse)(object)responseValue, question);
					try
					{
						source.SetResult(result);
					}
					catch (InvalidOperationException)
					{
						/* When deactivation occurrs, an exception 
						 * may be raised inexplicably on reactivation - ignore. */
					}
				};

			try
			{
				messageBox.Show();
			}
			catch (Exception ex)
			{
				source.SetException(ex);
			}

			return source.Task;
		}

		void AskQuestionWithTextResponse(
			TextResponseQuestion textResponseQuestion,
			Action<QuestionResult<TextResponse>> resultHandler)
		{
			try
			{
				AskQuestionWithTextResponseCore(textResponseQuestion, resultHandler);
			}
			catch (Exception ex)
			{
				Console.WriteLine(ex);
				Deployment.Current.Dispatcher.BeginInvoke(
					delegate
						{
							resultHandler(new QuestionResult<TextResponse>(null, textResponseQuestion, ex));
						});
			}
		}

		void AskQuestionWithTextResponseCore(
			TextResponseQuestion textResponseQuestion,
			Action<QuestionResult<TextResponse>> resultHandler)
		{
			OkCancelQuestionResult questionResult;

			Deployment.Current.Dispatcher.InvokeIfRequired(
				delegate
			        {
			        	try
			        	{
							InputScope inputScope = new InputScope();
							inputScope.Names.Add(new InputScopeName { NameValue = textResponseQuestion.InputScope });

							InputPrompt prompt = new InputPrompt
							                     	{
							                     		Title = textResponseQuestion.Caption, 
														Message = textResponseQuestion.Question,
														Value = textResponseQuestion.DefaultResponse,
														InputScope = inputScope
							                     	};

							prompt.Completed += (sender, args) =>
							                    	{
														if (args.Error != null)
														{
															resultHandler(new QuestionResult<TextResponse>(null, textResponseQuestion, args.Error));
															return;
														}

							                    		questionResult = args.PopUpResult == PopUpResult.OK 
															? OkCancelQuestionResult.Ok 
															: OkCancelQuestionResult.Cancel;

														var textResponse = new TextResponse(questionResult, args.Result);
														var result = new QuestionResult<TextResponse>(textResponse, textResponseQuestion);
														resultHandler(result);
							                    	};
			        		prompt.Show();
			        	}
			        	catch (Exception ex)
			        	{
			        		Console.WriteLine(ex);
							resultHandler(new QuestionResult<TextResponse>(null, textResponseQuestion, ex));
			        	}
			        });

		}
	}

//	public class TextResponseViewModel
//	{
//		public TextResponseQuestion TextResponseQuestion { get; private set; }
//		public string Response { get; set; }
//		public string Caption { get; private set; }
//		public string Question { get; private set; }
//
//		public TextResponseViewModel(TextResponseQuestion textResponseQuestion)
//		{
//			TextResponseQuestion = textResponseQuestion;
//			Caption = string.IsNullOrEmpty(textResponseQuestion.Caption) 
//				? "Question" : textResponseQuestion.Caption;
//			Question = textResponseQuestion.Question;
//		}
//	}
}
